# coding:utf-8
from odoo import models, fields, api, _
from odoo.exceptions import Warning
import odoo.addons.decimal_precision as dp
from odoo.exceptions import UserError
from datetime import datetime


class PaulResPartnerExtend(models.Model):
    _inherit = 'res.partner'

    billing_cycle = fields.Char('Billing Cycle')


class PaulAccountInvoiceExtend(models.Model):
    _inherit = 'account.invoice'
    _name = 'account.invoice'

    billing_cycle = fields.Char(related='partner_id.billing_cycle', string='Billing Cycle', store=True, readonly=True)
    invoice_id = fields.Many2one('account.invoice', String='Related Invoice',
                                 domain="[('partner_id', '=', partner_id), ('type', 'in', ('out_invoice', 'out_refund')),('state', 'in', ('open','paid','cancel'))]")
    payment_date = fields.Datetime('Payment Date')
    order_user_id = fields.Many2one('res.users', string=u'销售员', related='partner_id.user_id', readonly=True)
    is_submit = fields.Boolean('Is Submit', default=False)
    property_supplier_payment_term_id = fields.Char(related='partner_id.property_supplier_payment_term_id.name',
                                                    string='Payment Term', store=True, readonly=True)
    # property_supplier_payment_term_id = fields.Char(related='partner_id.property_supplier_payment_term_id.name',
    #                                                 string='Payment Term', store=True, readonly=True)
    vendor_payment_term_ids = fields.Many2many('account.payment.term', related='partner_id.vendor_payment_term_ids',
                                                 readonly=True)
    force_date = fields.Char(u'记账日期', help=u"来自出货单的强制日期", compute="_compute_deliver_info", store=False)
    deliver_order = fields.Char(u'送货单号', compute="_compute_deliver_info", store=False)

    def _compute_deliver_info(self):
        for ai in self:
            pickings = ai.invoice_line_ids.mapped('sale_line_ids').mapped('order_id').mapped('picking_ids')
            force_datetime = pickings.mapped('force_date')
            while False in force_datetime:
                force_datetime.remove(False)
            deliver_order = pickings.mapped('name')
            force_date = (datetime.strftime(datetime.strptime(d, '%Y-%m-%d %H:%M:%S'), '%Y年%m月%d日') for d in force_datetime)
            ai.force_date = ', '.join(set(force_date))
            ai.deliver_order = ', '.join(deliver_order)


    @api.onchange('partner_id')
    def _onchange_invoice_partner_id(self):
        return {
            'domain': {'payment_term_id': [('id', 'in', self.vendor_payment_term_ids.ids)]},
        }

    @api.onchange('invoice_line_ids')
    def _onchange_invoice_line_ids(self):
        taxes_grouped = self.get_taxes_values()
        tax_lines = self.tax_line_ids.filtered('manual')
        for tax in taxes_grouped.values():
            tax_lines += tax_lines.new(tax)
        self.tax_line_ids = tax_lines
        for line in self.invoice_line_ids:
            line.origin_price_unit = line.price_unit
        return

    # this alert move to write by judith request.
    # @api.multi
    # def action_invoice_open(self):
    #     for line in self.invoice_line_ids:
    #         if line.purchase_line_id:
    #             if round(line.price_unit, 4) != round(line.purchase_line_id.price_unit, 4):
    #                 if line.note is False or line.note == "":
    #                     raise Warning(u'请在行备注输入单价修改原因')
    #         else:
    #             if round(line.so_price_unit, 4) != round(line.price_unit, 4):
    #                 if line.note is False or line.note == "":
    #                     raise Warning(u'请输入单价修改原因')
    #     return super(PaulAccountInvoiceExtend, self).action_invoice_open()

    @api.model
    def name_search(self, name, args=None, operator='ilike', limit=100):
        args = args or []
        recs = self.browse()
        if name:
            recs = self.search([('number', operator, name)] + args, limit=limit)
        if not recs:
            recs = self.search([('name', operator, name)] + args, limit=limit)
        return recs.name_get()

    @api.model
    def create(self, vals):
        vals['is_submit'] = False
        return super(PaulAccountInvoiceExtend, self).create(vals)

    @api.multi
    def write(self, vals):
        sale_order = self.env['sale.order'].search([('name', '=', self.origin)])
        purchase_order = self.env['purchase.order'].search([('name', '=', self.origin)])
        deposit_product_id = self.env['ir.values'].get_default('sale.config.settings', 'deposit_product_id_setting')
        res = super(PaulAccountInvoiceExtend, self).write(vals)
        for line in self.invoice_line_ids:
            if line.purchase_line_id:
                if round(line.price_unit, 4) != round(line.purchase_line_id.price_unit, 4):
                    if line.note is False or line.note == "":
                        raise Warning(u'请在行备注输入单价修改原因')
            else:
                if round(line.so_price_unit, 4) != round(line.price_unit, 4):
                    if line.note is False or line.note == "":
                        raise Warning(u'请输入单价修改原因')
        if sale_order:
            for inv_line in self.invoice_line_ids:
                line_delivery = 0
                for l in inv_line.sale_line_ids:
                    line_delivery += l.qty_delivered
                inv_line.delivered_qty = line_delivery
                if inv_line.product_id.id != deposit_product_id and inv_line.product_id.type != 'service' and inv_line.quantity > inv_line.delivered_qty:
                    raise Warning(u'发票数量不可大于已出货数量')
        if purchase_order:
            for inv_line in self.invoice_line_ids:
                if inv_line.product_id.id != deposit_product_id and inv_line.product_id.type != 'service' and inv_line.quantity > inv_line.purchase_line_id.qty_received-inv_line.purchase_line_id.qty_returned:
                    raise Warning(u'账单开票数量不可大于实收数量-退货数量')
        return res

    @api.multi
    def action_view_po_by_invoice_ol(self):
        self.ensure_one()
        action = self.env.ref("purchase_order_extend.purchase_order_line_action")
        if not action:
            return True

        action_dict = action.read()[0]

        action_dict["domain"] = [("order_id", "=", self.env['purchase.order'].search([('name', '=', self.origin)]).id)]

        return action_dict

    @api.multi
    def action_submit_to_fin2(self):
        self.write({
            'is_submit': True
        })

    @api.multi
    def action_submit_to_fin(self):
        self.action_invoice_proforma2()
        self.write({
            'is_submit': True
        })

    @api.multi
    def action_invoice_draft(self):
        self.is_submit = False
        return super(PaulAccountInvoiceExtend, self).action_invoice_draft()


class PaulAccountInvoiceLineExtend(models.Model):
    _inherit = 'account.invoice.line'

    origin_qty = fields.Float('Origin Qty', readonly=True)
    delivered_qty = fields.Float('Delivered Qty', readonly=True, digits=dp.get_precision('Product Unit of Measure'))
    received_qty = fields.Float('Received Qty', readonly=True, digits=dp.get_precision('Product Unit of Measure'))
    origin_price_unit = fields.Float(string=u'原单价', readonly=True, digits=dp.get_precision('Product Price'))
    so_price_unit = fields.Float(string=u'SO单价', readonly=True, compute="_compute_so_price_unit",
                                 digits=dp.get_precision('Product Price'))
    note = fields.Text('Note')
    number = fields.Char(u'发票号码', related='invoice_id.number', readonly=True)
    date_invoice = fields.Date(u'对账截止日', related='invoice_id.date_invoice', readonly=True)
    reference = fields.Char(u'客户订单号', compute='_get_ref', readonly=True)
    date_due = fields.Date(u'付款日期', related='invoice_id.date_due', readonly=True)
    categ_id = fields.Char(string=u'产品类别', related='product_id.class_code1', readonly=True)
    amount_total = fields.Monetary(u'含税金额', compute='_compute_amount_total', readonly=True)
    net_length = fields.Float(u'纯长', compute="_get_net_length", digits=(16, 4))
    type = fields.Selection([
                                ('out_invoice', 'Customer Invoice'),
                                ('in_invoice', 'Vendor Bill'),
                                ('out_refund', 'Customer Refund'),
                                ('in_refund', 'Vendor Refund'),
                            ], readonly=True, related='invoice_id.type')
    state = fields.Selection([
                                 ('draft', 'Draft'),
                                 ('proforma', 'Pro-forma'),
                                 ('proforma2', 'Pro-forma'),
                                 ('open', 'Open'),
                                 ('paid', 'Paid'),
                                 ('cancel', 'Cancelled'),
                             ], readonly=True, related='invoice_id.state')
    is_export_xls = fields.Boolean('Already Export Excel Report', default=False)

    @api.multi
    def create(self, vals):
        vals['origin_qty'] = vals['quantity']
        # vals['origin_price_unit'] = vals['price_unit']
        return super(PaulAccountInvoiceLineExtend, self).create(vals)

    def _compute_amount_total(self):
        for line in self:
            line.update({'amount_total': line.quantity * line.price_unit})

    def _get_ref(self):
        for line in self:
            line.update({'reference': line.sale_line_ids and line.sale_line_ids[0].order_id.client_order_ref or False})

    def _get_net_length(self):
        for line in self:
            lot_uom_ratio = self.env['stock.production.lot'].search(
                [('product_id', '=', line.product_id.id), ('lot_uom_ratio', '!=', False)]).mapped('lot_uom_ratio')
            if lot_uom_ratio:
                line.update({'net_length': lot_uom_ratio[0]})

    def _compute_so_price_unit(self):
        for line in self:
            line.update({'so_price_unit': line.sale_line_ids and line.sale_line_ids[0].price_unit or False})


class OLAccountPaymentExtend(models.Model):
    _inherit = 'account.payment'
    _name = 'account.payment'

    @api.multi
    def post(self):
        for inv in self.invoice_ids:
            inv.payment_date = self.payment_date
        return super(OLAccountPaymentExtend, self).post()


class SaleAdvancePaymentInv(models.TransientModel):
    _inherit = "sale.advance.payment.inv"
    _name = "sale.advance.payment.inv"

    @api.multi
    def _create_invoice(self, order, so_line, amount):
        inv_obj = self.env['account.invoice']
        ir_property_obj = self.env['ir.property']

        account_id = False
        if self.product_id.id:
            account_id = self.product_id.property_account_income_id.id
        if not account_id:
            inc_acc = ir_property_obj.get('property_account_income_categ_id', 'product.category')
            account_id = order.fiscal_position_id.map_account(inc_acc).id if inc_acc else False
        if not account_id:
            raise UserError(
                _(
                    'There is no income account defined for this product: "%s". You may have to install a chart of account from Accounting app, settings menu.') %
                (self.product_id.name,))

        if self.amount <= 0.00:
            raise UserError(_('The value of the down payment amount must be positive.'))
        if self.advance_payment_method == 'percentage':
            amount = order.amount_untaxed * self.amount / 100
            name = _("Down payment of %s%%") % (self.amount,)
        else:
            amount = self.amount
            name = _('Down Payment')
        if order.fiscal_position_id and self.product_id.taxes_id:
            tax_ids = order.fiscal_position_id.map_tax(self.product_id.taxes_id).ids
        else:
            tax_ids = self.product_id.taxes_id.ids

        invoice = inv_obj.create({
            'name': order.client_order_ref or order.name,
            'origin': order.name,
            'type': 'out_invoice',
            'reference': False,
            'account_id': order.partner_id.property_account_receivable_id.id,
            'partner_id': order.partner_invoice_id.id,
            'partner_shipping_id': order.partner_shipping_id.id,
            'user_id': order.user_id.id,
            'invoice_line_ids': [(0, 0, {
                'name': name,
                'origin': order.name,
                'account_id': account_id,
                'price_unit': amount,
                'quantity': 1.0,
                'discount': 0.0,
                'uom_id': self.product_id.uom_id.id,
                'product_id': self.product_id.id,
                'sale_line_ids': [(6, 0, [so_line.id])],
                'invoice_line_tax_ids': [(6, 0, tax_ids)],
                'account_analytic_id': order.project_id.id or False,
            })],
            'currency_id': order.pricelist_id.currency_id.id,
            'payment_term_id': order.payment_term_id.id,
            'fiscal_position_id': order.fiscal_position_id.id or order.partner_id.property_account_position_id.id,
            'team_id': order.team_id.id,
            'comment': order.note,
        })
        invoice.compute_taxes()
        invoice.message_post_with_view('mail.message_origin_link',
                                       values={'self': invoice, 'origin': order},
                                       subtype_id=self.env.ref('mail.mt_note').id)
        return invoice
